﻿/*
COPYRIGHT (C) 2011-2013 Raynald Messié

THIS FILE IS PART OF SCRUMPILOT.

SCRUMPILOT IS FREE SOFTWARE: YOU CAN REDISTRIBUTE IT AND/OR MODIFY IT UNDER THE TERMS OF 
THE GNU LESSER GENERAL PUBLIC LICENSE VERSION v2.1 AS PUBLISHED BY THE FREE SOFTWARE FOUNDATION.

SCRUMPILOT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY WARRANTY; WITHOUT
EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU LESSER
GENERAL PUBLIC LICENSE FOR MORE DETAILS.

YOU SHOULD HAVE RECEIVED A COPY OF THE GNU LESSER GENERAL PUBLIC LICENSE ALONG WITH SCRUMPILOT. 
IF NOT, SEE <HTTP://WWW.GNU.ORG/LICENSES/>.
*/

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using ScrumPilot.Domain.Models;
using ScrumPilot.TFSHelpers;

namespace ScrumPilot.Domain.BPL
{
    public class WallServices : BusinessProcessLayer
    {
        public WallServices(TFSServices tfs) : base(tfs) { }
        public List<WallInfo> GetWallInfo(int first, int last, Int32 currentUser, CultureInfo ci, String tfsRootUrl)
        {
            using (var unitOfWork = new UnitOfWork())
            {
                CurrentCulture = ci;
                CurrentUserID = currentUser;

                var m = (FollowedProject != null && FollowedProject.Count() > 0) ? unitOfWork.EventRepository.Filter(p =>
                                                      (p.projectid.HasValue &&
                                                       FollowedProject.Contains(p.projectid.Value)) ||
                                                      p.projectid == null) : unitOfWork.EventRepository.All();

             
                if (FollowedUsers != null && FollowedUsers.Count > 0)
                    m = m.Where(p => (p.userid != null && FollowedUsers.Contains(p.userid.Value)) || p.userid == null);

                m = m.OrderByDescending(p => p.createdate).Skip(first).Take(last);
        
           
                var l = (from p in m
                         select new EventTmp
                                    {
                                        ID = p.eventid,
                                        Author = p.user.name,
                                        AuthorID = p.userid,
                                        Sentence = p.eventtype.exposedstring,
                                        ActionDate = p.createdate,
                                        XML = p.eventobject,
                                        TypeID = p.typeid,
                                        ProjectID = p.projectid,
                                        ProjectName = p.project.name
                                    }
                        ).Skip(first).Take(last);

                return GetBaseWallEvents(l, currentUser, tfsRootUrl);
            }
        }

        public List<WallInfo> GetWallInfo(DateTime lastDate, Int32 currentUser, CultureInfo ci, String tfsRootUrl)
        {
            using (var unitOfWork = new UnitOfWork())
            {
                CurrentCulture = ci;

                var m = unitOfWork.EventRepository.All();


                if (FollowedProject != null && FollowedProject.Count() > 0)
                    m =
                        m.Where(
                            p =>
                            p.projectid == null || (p.projectid != null && FollowedProject.Contains(p.projectid.Value)));

                var l = from p in m
                        where p.createdate > lastDate
                        orderby p.createdate descending
                        select new EventTmp
                                   {
                                       ID = p.eventid,
                                       Author = p.user.name,
                                       AuthorID = p.userid,
                                       Sentence = p.eventtype.exposedstring,
                                       ActionDate = p.createdate,
                                       XML = p.eventobject,
                                       TypeID = p.typeid,
                                       ProjectID = p.projectid,
                                       ProjectName = p.project.name
                                   };

                return GetBaseWallEvents(l, currentUser, tfsRootUrl);
            }
        }

        public List<WallInfo> GetUserWallInfo(int first, int last, int userID, Int32 currentUser, CultureInfo ci, String tfsRootUrl)
        {
            using (var unitOfWork = new UnitOfWork())
            {
                CurrentCulture = ci;

                var m = (FollowedProject != null && FollowedProject.Count() > 0) ? unitOfWork.EventRepository.Filter(p =>
                                                      (p.projectid.HasValue &&
                                                       FollowedProject.Contains(p.projectid.Value)) ||
                                                      p.projectid == null) : unitOfWork.EventRepository.All();

                m = m.Where(p => p.userid == userID).OrderByDescending(p=>p.createdate).Skip(first).Take(last);
                var l = (from p in m
                         select new EventTmp
                                    {
                                        ID = p.eventid,
                                        Author = p.user.name,
                                        AuthorID = p.userid,
                                        Sentence = p.eventtype.exposedstring,
                                        ActionDate = p.createdate,
                                        XML = p.eventobject,
                                        TypeID = p.typeid,
                                        ProjectID = p.projectid,
                                        ProjectName = p.project.name
                                    }).Skip(first).Take(last);

                return (GetBaseWallEvents(l, currentUser, tfsRootUrl));
            }
        }

        public List<WallInfo> GetProjectWallInfo(int first, int last, Int32 projectID, Int32 currentUser,
                                                        CultureInfo ci, String tfsRootUrl)
        {
            using (var unitOfWork = new UnitOfWork())
            {
                CurrentCulture = ci;

                var m = (from p in unitOfWork.EventRepository.All()
                         where p.projectid == projectID
                         orderby p.speventcomments.Max(c => c.createdate) ?? p.createdate descending
                         select new EventTmp
                                    {
                                        ID = p.eventid,
                                        Author = p.user.name,
                                        AuthorID = p.userid,
                                        Sentence = p.eventtype.exposedstring,
                                        ActionDate = p.speventcomments.Max(c => c.createdate) ?? p.createdate,
                                        XML = p.eventobject,
                                        TypeID = p.typeid,
                                        ProjectID = p.projectid,
                                        ProjectName = p.project.name
                                    }).Skip(first).Take(last);

                return (GetBaseWallEvents(m, currentUser, tfsRootUrl));
            }
        }

        public List<WallComment> GetEventComments(Int64 id, Int32 currentUser, CultureInfo ci)
        {
            using (var unitOfWork = new UnitOfWork())
            {
                CurrentCulture = ci;

                var l = unitOfWork.EventRepository.GetById(id).speventcomments.OrderByDescending(p => p.createdate).ToArray();
                List<WallComment> lstComment = l.Any() ? new List<WallComment>(l.Count()) : null;
                if (lstComment != null)
                {
                    lstComment.AddRange(l.Select(se => se.userid != null ? new WallComment
                                                                               {
                                                                                   ID = se.eventcommentid,
                                                                                   AuthorID = (int)se.userid,
                                                                                   Author = unitOfWork.UserRepositery.GetById(se.userid.Value).name,
                                                                                   Comment = se.comments,
                                                                                   date = se.createdate ?? DateTime.UtcNow,
                                                                                   CanDelete = ((int)se.userid) == currentUser
                                                                               } : null));

                }
                return lstComment;
            }
        }

        public Int64 CreateComment(Int32 usr, Int64 id, String comment)
        {
            Int64 lRet = -1;
            //if (!String.IsNullOrWhiteSpace(comment))
            //{
            //    var spev = new speventcomment
            //    {
            //        userid = usr,
            //        createdate = DateTime.UtcNow,
            //        eventid = id,
            //        comments = comment
            //    };
            //    DB.AddTospeventcomments(spev);
            //    if (DB.SaveChanges() > 0)
            //        lRet = spev.eventcommentid;
            //}
            return lRet;
        }

        public bool DeleteComment(Int32 usr, Int64 id)
        {
            //Boolean bRet = false;
            //speventcomment spc = DB.speventcomments.FirstOrDefault(p => p.eventcommentid == id);
            //if (spc != null && spc.userid == usr)
            //{
            //    DB.DeleteObject(spc);
            //    bRet = (DB.SaveChanges() > 0);
            //}
            return false;
        }

        private List<WallInfo> GetBaseWallEvents(IQueryable<EventTmp> l, int currentUser, String tfsRootUrl)
        {
            var lstRet = new List<WallInfo>(l.Count());
            foreach (var eventTmp in l)
            {
                lstRet.Add(GetBaseWallEvent(eventTmp, currentUser, tfsRootUrl));
            }
            return lstRet.OrderByDescending(p => p.Date).ToList();
        }

        private WallInfo GetBaseWallEvent(EventTmp l, int currentUser, String tfsRootUrl)
        {
            var wRet = new WallInfo
            {
                ID = l.ID,
                Author = l.Author,
                AuthorID = l.AuthorID,
                Date = new DateTime(l.ActionDate.Ticks, DateTimeKind.Utc),
                ProjectID = l.ProjectID,
                ProjectName = l.ProjectName,
                //Comments = GetEventComments(l.ID, currentUser, CurrentCulture)
            };

            if (l.TypeID < 3) // Todo : Should be a field in DB : noTFSEvent
            {
                TFSWallContentObject tfsR = TFS.GetWallContent(l.XML, l.TypeID, l.ID, tfsRootUrl);

                if (String.IsNullOrWhiteSpace(l.ProjectName) && tfsR != null && !String.IsNullOrEmpty(tfsR.ProjectName))
                {
                    using (var unitOfWork = new UnitOfWork())
                    {
                        var prj = unitOfWork.ProjectRepository.Get(p => p.name == tfsR.ProjectName);
                        if (prj != null)
                        {
                            l.ProjectName = tfsR.ProjectName;
                            l.ProjectID = prj.projectid;
                        }
                        wRet.Sentence = String.Format(l.Sentence, tfsR.Name);
                        wRet.Description = tfsR.Descriptions;
                        wRet.URLDetail = tfsR.Url;
                        wRet.MoreInformation = tfsR.More;
                        wRet.ProjectID = l.ProjectID;
                    }
                }
            }
            else
            {
                if (l.TypeID == 3)
                {
                    wRet.Sentence = l.Sentence ?? "";
                    wRet.Description = l.XML;
                }
            }

            return wRet;
        }

        private class EventTmp
        {
            public Int64 ID { get; set; }
            public string Author { get; set; }
            public Nullable<Int32> AuthorID { get; set; }
            public string Sentence { get; set; }
            public DateTime ActionDate { get; set; }
            public string XML { get; set; }
            public Int32 TypeID { get; set; }
            public Nullable<Int32> ProjectID { get; set; }
            public string ProjectName { get; set; }
        }
    }
}
